/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package bpel2rep.version.impl;

import bpel2rep.exception.UnknownStateNameException;
import bpel2rep.version.MetaInfo;
import bpel2rep.version.StateName;
import bpel2rep.version.Version;
import bpel2rep.version.VersionId;
import bpel2rep.version.VersionPackage;
import bpel2rep.version.VersionState;
import bpel2rep.version.VersionStore;
import bpel2rep.version.WorkingStatus;
import bpel2rep.version.state.StateFactory;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;

import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.impl.EObjectImpl;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Version</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getVersionState <em>Version State</em>}</li>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getMetaInfo <em>Meta Info</em>}</li>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getProcess <em>Process</em>}</li>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getPredecessor <em>Predecessor</em>}</li>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getVersionId <em>Version Id</em>}</li>
 *   <li>{@link bpel2rep.version.impl.VersionImpl#getStateName <em>State Name</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class VersionImpl extends EObjectImpl implements Version {
	
	VersionState freeState;
	VersionState lockWorkState;
	VersionState simuleSessionState;
	VersionState initialState;
	VersionStore vs;

	/**
	 * The cached value of the '{@link #getVersionState() <em>Version State</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getVersionState()
	 * @generated
	 * @ordered
	 */
	protected VersionState versionState;

	/**
	 * The cached value of the '{@link #getMetaInfo() <em>Meta Info</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getMetaInfo()
	 * @generated
	 * @ordered
	 */
	protected MetaInfo metaInfo;

	/**
	 * The cached value of the '{@link #getProcess() <em>Process</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getProcess()
	 * @generated
	 * @ordered
	 */
	protected bpel2rep.process.Process process;

	/**
	 * The cached value of the '{@link #getPredecessor() <em>Predecessor</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getPredecessor()
	 * @generated
	 * @ordered
	 */
	protected VersionId predecessor;

	/**
	 * The cached value of the '{@link #getVersionId() <em>Version Id</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getVersionId()
	 * @generated
	 * @ordered
	 */
	protected VersionId versionId;

	/**
	 * The default value of the '{@link #getStateName() <em>State Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getStateName()
	 * @generated
	 * @ordered
	 */
	protected static final StateName STATE_NAME_EDEFAULT = StateName.LOCK_WORK;
	/**
	 * The cached value of the '{@link #getStateName() <em>State Name</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getStateName()
	 * @generated
	 * @ordered
	 */
	protected StateName stateName = STATE_NAME_EDEFAULT;

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	protected VersionImpl() {
		super();
	}

	public VersionImpl(VersionStore vs) {
		this.vs = vs;
		//TODO: implement rest state initialize
		this.freeState = StateFactory.eINSTANCE.createFree(this);
		this.lockWorkState = StateFactory.eINSTANCE.createLockWork(this);
		this.initialState = StateFactory.eINSTANCE.createInitial(this);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return VersionPackage.Literals.VERSION;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public VersionState getVersionState() {
		return versionState;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetVersionState(VersionState newVersionState, NotificationChain msgs) {
		VersionState oldVersionState = versionState;
		versionState = newVersionState;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__VERSION_STATE, oldVersionState, newVersionState);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setVersionState(VersionState newVersionState) {
		if (newVersionState != versionState) {
			NotificationChain msgs = null;
			if (versionState != null)
				msgs = ((InternalEObject)versionState).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__VERSION_STATE, null, msgs);
			if (newVersionState != null)
				msgs = ((InternalEObject)newVersionState).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__VERSION_STATE, null, msgs);
			msgs = basicSetVersionState(newVersionState, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__VERSION_STATE, newVersionState, newVersionState));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public MetaInfo getMetaInfo() {
		return metaInfo;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetMetaInfo(MetaInfo newMetaInfo, NotificationChain msgs) {
		MetaInfo oldMetaInfo = metaInfo;
		metaInfo = newMetaInfo;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__META_INFO, oldMetaInfo, newMetaInfo);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setMetaInfo(MetaInfo newMetaInfo) {
		if (newMetaInfo != metaInfo) {
			NotificationChain msgs = null;
			if (metaInfo != null)
				msgs = ((InternalEObject)metaInfo).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__META_INFO, null, msgs);
			if (newMetaInfo != null)
				msgs = ((InternalEObject)newMetaInfo).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__META_INFO, null, msgs);
			msgs = basicSetMetaInfo(newMetaInfo, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__META_INFO, newMetaInfo, newMetaInfo));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public bpel2rep.process.Process getProcess() {
		return process;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetProcess(bpel2rep.process.Process newProcess, NotificationChain msgs) {
		bpel2rep.process.Process oldProcess = process;
		process = newProcess;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__PROCESS, oldProcess, newProcess);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setProcess(bpel2rep.process.Process newProcess) {
		if (newProcess != process) {
			NotificationChain msgs = null;
			if (process != null)
				msgs = ((InternalEObject)process).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__PROCESS, null, msgs);
			if (newProcess != null)
				msgs = ((InternalEObject)newProcess).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__PROCESS, null, msgs);
			msgs = basicSetProcess(newProcess, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__PROCESS, newProcess, newProcess));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public VersionId getPredecessor() {
		return predecessor;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetPredecessor(VersionId newPredecessor, NotificationChain msgs) {
		VersionId oldPredecessor = predecessor;
		predecessor = newPredecessor;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__PREDECESSOR, oldPredecessor, newPredecessor);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setPredecessor(VersionId newPredecessor) {
		if (newPredecessor != predecessor) {
			NotificationChain msgs = null;
			if (predecessor != null)
				msgs = ((InternalEObject)predecessor).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__PREDECESSOR, null, msgs);
			if (newPredecessor != null)
				msgs = ((InternalEObject)newPredecessor).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__PREDECESSOR, null, msgs);
			msgs = basicSetPredecessor(newPredecessor, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__PREDECESSOR, newPredecessor, newPredecessor));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public VersionId getVersionId() {
		return versionId;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public NotificationChain basicSetVersionId(VersionId newVersionId, NotificationChain msgs) {
		VersionId oldVersionId = versionId;
		versionId = newVersionId;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__VERSION_ID, oldVersionId, newVersionId);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void setVersionId(VersionId newVersionId) {
		if (newVersionId != versionId) {
			NotificationChain msgs = null;
			if (versionId != null)
				msgs = ((InternalEObject)versionId).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__VERSION_ID, null, msgs);
			if (newVersionId != null)
				msgs = ((InternalEObject)newVersionId).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - VersionPackage.VERSION__VERSION_ID, null, msgs);
			msgs = basicSetVersionId(newVersionId, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__VERSION_ID, newVersionId, newVersionId));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public StateName getStateName() {
		return stateName;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @throws UnknownStateNameException 
	 * @generated NOT
	 */
	public void setStateName(StateName newStateName) throws UnknownStateNameException {
		StateName oldStateName = stateName;
		stateName = newStateName == null ? STATE_NAME_EDEFAULT : newStateName;
		//TODO: synchronization other state according to statename
		if(newStateName == StateName.FREE)
			this.setVersionState(this.getFreeState());
		else if (newStateName == StateName.LOCK_WORK)
			this.setVersionState(this.getLockWorkState());
		else if (newStateName == StateName.INITIAL)
			this.setVersionState(this.getInitialState());
		else
			throw new UnknownStateNameException(stateName.toString() + "is an unknown statename");
			
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, VersionPackage.VERSION__STATE_NAME, oldStateName, stateName));
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public void checkin(Version version, boolean isMajor, WorkingStatus ws) {
		this.versionState.checkin(version, isMajor, ws);
	}

	/**
	 * <!-- begin-user-doc -->
	 * return null, if version can not be checkout
	 * the user of this function should handle the status
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public Version checkout(String processId, VersionId versionId, WorkingStatus ws) {
		// first find out the state of version Name then initialize 
		// versionState
		StateName sn = this.vs.getStateName(processId, versionId);
		try {
			this.setStateName(sn);
		} catch (UnknownStateNameException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Version v = this.versionState.checkout(processId, versionId,ws);
		
		return v;
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void checkoutuse() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void endSimuleSession() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void startSimuleSession() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void lockUse() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void lockWork() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void lockSimule() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void unlockSimule() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void unlockUse() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	public void unlockWork() {
		// TODO: implement this method
		// Ensure that you remove @generated or mark it @generated NOT
		throw new UnsupportedOperationException();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case VersionPackage.VERSION__VERSION_STATE:
				return basicSetVersionState(null, msgs);
			case VersionPackage.VERSION__META_INFO:
				return basicSetMetaInfo(null, msgs);
			case VersionPackage.VERSION__PROCESS:
				return basicSetProcess(null, msgs);
			case VersionPackage.VERSION__PREDECESSOR:
				return basicSetPredecessor(null, msgs);
			case VersionPackage.VERSION__VERSION_ID:
				return basicSetVersionId(null, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case VersionPackage.VERSION__VERSION_STATE:
				return getVersionState();
			case VersionPackage.VERSION__META_INFO:
				return getMetaInfo();
			case VersionPackage.VERSION__PROCESS:
				return getProcess();
			case VersionPackage.VERSION__PREDECESSOR:
				return getPredecessor();
			case VersionPackage.VERSION__VERSION_ID:
				return getVersionId();
			case VersionPackage.VERSION__STATE_NAME:
				return getStateName();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case VersionPackage.VERSION__VERSION_STATE:
				setVersionState((VersionState)newValue);
				return;
			case VersionPackage.VERSION__META_INFO:
				setMetaInfo((MetaInfo)newValue);
				return;
			case VersionPackage.VERSION__PROCESS:
				setProcess((bpel2rep.process.Process)newValue);
				return;
			case VersionPackage.VERSION__PREDECESSOR:
				setPredecessor((VersionId)newValue);
				return;
			case VersionPackage.VERSION__VERSION_ID:
				setVersionId((VersionId)newValue);
				return;
			case VersionPackage.VERSION__STATE_NAME:
				try {
					setStateName((StateName)newValue);
				} catch (UnknownStateNameException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case VersionPackage.VERSION__VERSION_STATE:
				setVersionState((VersionState)null);
				return;
			case VersionPackage.VERSION__META_INFO:
				setMetaInfo((MetaInfo)null);
				return;
			case VersionPackage.VERSION__PROCESS:
				setProcess((bpel2rep.process.Process)null);
				return;
			case VersionPackage.VERSION__PREDECESSOR:
				setPredecessor((VersionId)null);
				return;
			case VersionPackage.VERSION__VERSION_ID:
				setVersionId((VersionId)null);
				return;
			case VersionPackage.VERSION__STATE_NAME:
				try {
					setStateName(STATE_NAME_EDEFAULT);
				} catch (UnknownStateNameException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case VersionPackage.VERSION__VERSION_STATE:
				return versionState != null;
			case VersionPackage.VERSION__META_INFO:
				return metaInfo != null;
			case VersionPackage.VERSION__PROCESS:
				return process != null;
			case VersionPackage.VERSION__PREDECESSOR:
				return predecessor != null;
			case VersionPackage.VERSION__VERSION_ID:
				return versionId != null;
			case VersionPackage.VERSION__STATE_NAME:
				return stateName != STATE_NAME_EDEFAULT;
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (StateName: ");
		result.append(stateName);
		result.append(')');
		return result.toString();
	}

	
	public VersionState getFreeState() {
		return this.freeState;
	}


	public VersionState getLockWorkState() {
		return this.lockWorkState;
	}


	public VersionState getSimuleSessionState() {
		return this.simuleSessionState;
	}



	public VersionState getInitialState() {
		return this.initialState;
	}


	public VersionStore getVersionStore() {
		return this.vs;
	}
} //VersionImpl
